using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.Security;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;
using PS.Practices.Provisioner;
using PS.Practices.SiteBuilder.Features.Schema;
using PS.Practices.Util;
using PrincipalListRole = PS.Practices.SiteBuilder.Features.Schema.DOM.PrincipalListRole;
using Template = PS.Practices.SiteBuilder.Features.Schema.DOM.Template;
using SysWebPart = System.Web.UI.WebControls.WebParts.WebPart;

#if MOSS
using Microsoft.SharePoint.Publishing;
#endif

namespace PS.Practices.SiteBuilder.Features.API
{
    public abstract class PSObject
    {
        private SPWeb web;

        public SPWeb Web
        {
            get { return web; }
            set
            {
                web = value;
            }
        }

        public PSObject(SPWeb web)
        {
            this.web = web;
        }
    }

    public class PSWebPart : PSObject, IDisposable
    {
        private string title;
        protected SPLimitedWebPartManager manager;
        private SysWebPart webPart;

        public string Title
        {
            get { return title; }
            set { title = value; }
        }

        public SysWebPart WebPart
        {
            get { return webPart; }
            set { webPart = value; }
        }

        public PSWebPart(SPWeb web, string filePath, string webPartTitle)
            : base(web)
        {
            if (web == null || string.IsNullOrEmpty(filePath) || string.IsNullOrEmpty(webPartTitle))
                throw new ArgumentNullException();

            Title = webPartTitle;
            WebPart = FindWebPart(filePath);
            if (WebPart == null)
                throw new ArgumentException(string.Format("web part {0} not found in file {1}",
                                                          webPartTitle, filePath));
        }

        private SysWebPart FindWebPart(string filePath)
        {
            SysWebPart pageWebPart = null;
            SPFile spFile = Web.GetFile(filePath);
            manager = spFile.GetLimitedWebPartManager(PersonalizationScope.Shared);

            SPLimitedWebPartCollection pageWebParts = manager.WebParts;
            if (pageWebParts != null)
            {
                foreach (SysWebPart part in pageWebParts)
                {
                    if (WebPart.Title == Title)
                    {
                        pageWebPart = part;
                        break;
                    }
                }
                //if (FindWebPart(pageWebParts, webPart, out pageWebPart))
                //{
                //    bool saveChanges = webPart.Process(pageWebPart, web, manager);
                //    if (saveChanges)
                //    {
                //        try
                //        {
                //            manager.SaveChanges(pageWebPart);
                //        }
                //        catch (WebPartPageUserException)
                //        {
                //        }
                //    }
                //}
            }

            //fix: Dispose/Close was not called on SPLimitedWebPartManager.Web
            manager.Web.Dispose();

            return pageWebPart;
        }

        //public static PSWebPart Create(SPWeb web, string filePath, string title)
        //{
        //    SPFile spFile = web.GetFile(filePath);

        //}

        //public static PSWebPart Create(SPWeb web, SPFile file)
        //{
        //    throw new NotImplementedException();
        //}

        /// <summary>
        /// Sets web part property value
        /// </summary>
        /// <param name="name">property name</param>
        /// <param name="value">new property value</param>
        public void SetProperty(string name, string value)
        {
            if (!string.IsNullOrEmpty(name) && !string.IsNullOrEmpty(value))
            {
                WebPartUtil.SetWPProperty(WebPart, name, value, Web);
            }
        }

        /// <summary>
        /// Sets new web part title 
        /// </summary>
        /// <param name="newTitle">New title</param>
        public void UpdateTitle(string newTitle)
        {
            ParserUtil.UpdateWPTitle(WebPart, Web, newTitle, null);
        }

        /// <summary>
        /// Saves performed changes
        /// </summary>
        public void SaveChanges()
        {
            manager.SaveChanges(WebPart);
        }


        /// <summary>
        /// Saves performed changes and disposes resources
        /// </summary>
        public void Dispose()
        {
            if (manager != null)
            {
                SaveChanges();
                manager.Dispose();
            }
        }
    }

    public class PSListViewWebPart : PSWebPart
    {
        private ListViewWebPart lvWebPart;
        public PSListViewWebPart(SPWeb web, string filePath, string webPartTitle)
            : base(web, filePath, webPartTitle)
        {
            if (!(WebPart is ListViewWebPart))
                throw new ArgumentException(webPartTitle + " is not ListViewWebPart", webPartTitle);

            lvWebPart = (ListViewWebPart)WebPart;
        }

        public void SetListViewAndToolbar(string listName, string viewName, string toolbarName)
        {
            SPList list = null;
            if (!string.IsNullOrEmpty(listName))
            {
                try
                {
                    list = Web.GetList(listName);
                }
                catch (SPException)
                {
                }
            }

            if (list == null)
            {
                try
                {
                    Guid listGuid = new Guid(lvWebPart.ListName);
                    list = Web.Lists[listGuid];
                }
                catch (FormatException)
                {
                }
                catch (SPException)
                {
                }

                if (list == null)
                {
                    try
                    {
                        list = Web.Lists[listName];
                    }
                    catch (SPException)
                    {
                    }
                }
            }

            if (list == null)
            {
                Logger.Info("Could not resolve list from web: " + Web.Title);
                return;
            }

            SPView view;
            if (!string.IsNullOrEmpty(viewName))
            {
                view = list.Views[viewName];

            }
            else
            {
                view = list.Views[new Guid(lvWebPart.ViewGuid)];
            }

            uint toolbar = 0;
            if (!string.IsNullOrEmpty(toolbarName))
            {
                if (!uint.TryParse(toolbarName, out toolbar))
                {
                    switch (toolbarName)
                    {
                        case "Standard":
                            toolbar = 0;
                            break;
                        case "Freeform":
                            toolbar = 1;
                            break;
                        default:
                            toolbar = 2;
                            break;
                    }
                }
            }
            WebPartUtil.SetListViewWebPartView(lvWebPart, view, toolbar, manager);
        }
    }

    public class PSList : PSObject
    {
        private bool enableContentType;
        private SPList spList;

        public bool EnableContentType
        {
            get { return enableContentType; }
            set { enableContentType = value; }
        }

        //public static PSList CreateFromSP(SPWeb web, SPList list, bool enableContentType)
        //{
        //    throw new NotImplementedException();
        //}

        public PSList(SPWeb web, string title, bool enableContentType)
            : base(web)
        {
            this.enableContentType = enableContentType;
            if (web == null || string.IsNullOrEmpty(title))
                throw new ArgumentNullException();

            try
            {
                spList = web.Lists[title];
            }
            catch (IndexOutOfRangeException)
            { }
            catch (ArgumentException)
            { }

            if (spList == null)
                throw new ArgumentException("can't find list with title " + title, "title");
        }

        /// <summary>
        /// Updates field
        /// </summary>
        /// <param name="name">Static or Display name</param>
        /// <param name="description">Description</param>
        /// <param name="dumpFields">Write or not fields to log</param>
        /// <param name="linkToLocalCTypes">Link field to local content types</param>
        /// <param name="defaultValue">Field default value</param>
        public void UpdateField(string name, string description, bool dumpFields,
            bool linkToLocalCTypes, string defaultValue)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentNullException("name");

            SPField field = GetField(name);

            if (field == null)
            {
                Logger.Info("Could not find field " + name + " in list " + spList.Title);
                return;
            }

            Logger.Info("Updating field " + field.StaticName + " in list " + spList.Title + ". ID=" + field.Id + ", SourceID=" + field.SourceId);

            if (string.IsNullOrEmpty(description))
            {
                field.Description = ParserUtil.ReplaceLiveFields(description, spList, Web);
                Logger.Info("Description set to: " + field.Description);
            }

            if (dumpFields)
            {
                foreach (SPField spField in spList.Fields)
                {
                    Logger.Info(spList.Title + ": {" + spField.Id + "} -- " + spField.StaticName + " : " + spField.Title);
                }
            }

            if (linkToLocalCTypes)
            {
                Logger.Info("Adding field " + field.StaticName + " to all local list content types ");
                ListUtil.LinkFieldToListCTypes(field, spList);
            }

            if (!string.IsNullOrEmpty(defaultValue))
            {
                string prevDef = field.DefaultValue;
                string curDef = ParserUtil.ReplaceLiveFields(defaultValue, spList, Web);
                field.DefaultValue = curDef;

                Logger.Info("Default value of '" + prevDef + "' replaced with '" + field.DefaultValue + "'");
            }

            field.Update(true);
        }

        private SPField GetField(string name)
        {
            SPField field = null;
            try
            {
                field = spList.Fields.GetFieldByInternalName(name);
            }
            catch (Exception)
            { }

            if (field == null)
            {
                try
                {
                    field = spList.Fields[name];
                }
                catch (Exception)
                { }
            }
            return field;
        }

        public void SetChoises(IEnumerable<string> choices, string fieldName, bool flush)
        {
            SPField field = GetField(fieldName);
            if (field == null)
                return;

            SPFieldChoice choice = field as SPFieldChoice;
            SPFieldMultiChoice mchoice = field as SPFieldMultiChoice;

            if (choice != null || mchoice != null)
            {
                if (choices != null)
                {
                    StringBuilder sb = new StringBuilder();
                    StringCollection coll = choice != null ? choice.Choices : mchoice.Choices;
                    if (flush)
                    {
                        coll.Clear();
                        sb.Append("#Flush# ");
                    }

                    foreach (string fieldChoise in choices)
                    {
                        string s = ParserUtil.ReplaceLiveFields(fieldChoise, spList, Web);
                        sb.Append(s + "; ");
                        coll.Add(s);
                    }

                    Logger.Info("Choices added: " + sb);
                }
            }

            field.Update(true);
        }

        public void AddField(string fieldName, bool addToDefaultView)
        {
            Logger.Info("Adding field: " + fieldName);
            spList.Fields.AddFieldAsXml(fieldName, addToDefaultView, SPAddFieldOptions.AddToAllContentTypes);
        }

        public void AddContentType(string contentTypeID, bool updateList)
        {
            ListUtil.AddCType(spList, contentTypeID);
            if (updateList)
            {
                spList.Update();
            }
        }

        public void RevomeContentType(string contentTypeID, bool updateList)
        {
            ListUtil.RemoveCType(spList, contentTypeID);
            if (updateList)
            {
                spList.Update();
            }
        }

        public void ReorderContentTypes()
        {
            ListUtil.ReorderCTypes(spList);
        }

        //public void FixupACL(string roleAssigments, IEnumerable<PrincipalListRole> roles)
        //{}

        public void ReplaceInTitle(string oldValue, string newValue)
        {
            string title = spList.Title;
            newValue = ParserUtil.ReplaceLiveFields(newValue, spList, Web);
            title = title.Replace(oldValue, newValue);
            spList.Title = title;
        }

        public class PSView
        {
            private string name;
            private SPView view;
            private SPList list;

            public string Name
            {
                get { return name; }
                set { name = value; }
            }

            public PSView(SPView view, SPList list)
            {
                if (view == null || list == null)
                    throw new ArgumentNullException();

                this.view = view;
                this.list = list;
            }

            public void InjectContentTypeFields(int position, IEnumerable<string> lessFields)
            {
                if (position > view.ViewFields.Count)
                    position = view.ViewFields.Count;


                StringCollection less = new StringCollection();
                foreach (string lessField in lessFields)
                {
                    less.Add(lessField);
                }

                ListUtil.InjectFieldsFromCTypes(view, list.ContentTypes, position, less);
            }
        }

        public PSView GetView(string viewName)
        {
            PSView view = null;
            try
            {
                SPView v = spList.Views[viewName];
                if (v != null)
                {
                    view = new PSView(v, spList);
                }
            }
            catch (SPException)
            { }
            return view;
        }
    }

    public class PSAcl : PSObject
    {
        protected SPSecurableObject securableObj;
        //protected SPWeb web;

        public PSAcl(SPSecurableObject securableObject, SPWeb web)
            : base(web)
        {
            securableObj = securableObject;
        }

        public void AddSiteGroup(string name, string role)
        {
            name = ParserUtil.ReplaceLiveFields(name, Web);
            SPPrincipal principal = AclUtil.ResolveSiteGroup(name, Web);
            if (principal != null)
            {
                AclUtil.AddPrincipal(principal, role, securableObj, Web);
            }
        }

        public void RemoveSiteGroup(string name, string role)
        {
            name = ParserUtil.ReplaceLiveFields(name, Web);
            SPPrincipal principal = AclUtil.ResolveSiteGroup(name, Web);

            if (string.IsNullOrEmpty(role))
            {
                if (principal != null)
                {
                    AclUtil.RemovePrincipal(principal, securableObj, Web);
                }
            }
            else
            {
                RemovePrincipal(principal, role);
            }
        }

        private void RemovePrincipal(SPPrincipal principal, string role)
        {
            SPRoleDefinition definition = Web.RoleDefinitions[role];
            SPRoleAssignment roleAssignment = securableObj.RoleAssignments.GetAssignmentByPrincipal(principal);
            if (roleAssignment != null)
            {
                roleAssignment.RoleDefinitionBindings.Remove(definition);
                roleAssignment.Update();
            }
        }

        public void AddFbaRole(string name, string role)
        {
            name = ParserUtil.ReplaceLiveFields(name, Web);
            string rolePrefix = Roles.Provider.Name;
            SPPrincipal principal = AclUtil.ResolveUser(rolePrefix + ":" + name, Web, true);
            if (principal != null && !string.IsNullOrEmpty(role))
            {
                AclUtil.AddPrincipal(principal, role, securableObj, Web);
            }
        }

        public void RemoveFbaRole(string name, string role)
        {
            name = ParserUtil.ReplaceLiveFields(name, Web);
            string rolePrefix = Roles.Provider.Name;
            SPPrincipal principal = AclUtil.ResolveUser(rolePrefix + ":" + name, Web);
            if (principal != null && !string.IsNullOrEmpty(role))
            {
                AclUtil.RemovePrincipal(principal, securableObj, Web);
            }
        }

        public void AddUser(string name, string role)
        {
            name = ParserUtil.ReplaceLiveFields(name, Web);
            SPPrincipal principal = AclUtil.ResolveUser(name, Web);
            if (principal != null)
            {
                AclUtil.AddPrincipal(principal, role, securableObj, Web);
            }
        }

        public void RemoveUser(string name, string role)
        {
            name = ParserUtil.ReplaceLiveFields(name, Web);
            SPPrincipal principal = AclUtil.ResolveUser(name, Web);
            if (string.IsNullOrEmpty(role))
            {
                if (principal != null)
                {
                    AclUtil.RemovePrincipal(principal, securableObj, Web);
                }
            }
            else
            {
                RemovePrincipal(principal, role);
            }
        }
    }

    public class PSWebAcl //: PSAcl
    {
        private SPWeb web;

        public PSWebAcl(SPWeb web)
        //   : base(securableObject, web)
        {
            this.web = web;
        }

        //         public static PSAcl Create(ISecurableObject securableObject)
        //         {}

        public void ChangeInheritTopNav(bool newInheritTopNav)
        {
            if (newInheritTopNav != web.Navigation.UseShared)
            {
                web.Navigation.UseShared = newInheritTopNav;
                web.Update();
            }
        }

        public void ChangeRoleAssignments(string roleAssignments)
        {
            if (!string.IsNullOrEmpty(roleAssignments))
            {
                if (roleAssignments.StartsWith("Break"))
                {
                    Logger.Info("Breaking role inheritance: " + roleAssignments);
                    try
                    {
                        web.BreakRoleInheritance(roleAssignments == "BreakAndCopy");
                    }
                    catch (Exception e)
                    {
                        Logger.Info("Error while braking web role inheritance: " + roleAssignments);
                        Logger.Error(e);
                    }
                }
            }
        }

        /// <summary>
        /// Changes quick launch panel on "people and groups" configuration page
        /// </summary>
        public void SyncGroupQuickLaunch(string syncGroupQuickLaunch)
        {
            Logger.Info("Syncing group quick launch");
            AclUtil.SyncGroupQuickLaunch(web, syncGroupQuickLaunch == "FromAssociations");
        }

        /// <summary>
        /// Changes quick launch panel on "people and groups" configuration page
        /// </summary>
        /// <param name="groups">Groups to be in quick launch list</param>
        public void SyncGroupQuickLaunch(IEnumerable<string> groups)
        {
            List<SPGroup> grps = new List<SPGroup>();

            foreach (string groupName in groups)
            {
                string name = ParserUtil.ReplaceLiveFields(groupName, web);
                SPGroup group = AclUtil.ResolveSiteGroup(name, web);
                if (group != null)
                {
                    grps.Add(group);
                }
            }

            AclUtil.SyncGroupQuickLaunch(web, grps);
        }

        /// <summary>
        /// Sets SPGroup object to specific role
        /// </summary>
        /// <param name="name">group name</param>
        /// <param name="role">role name</param>
        public void AssociateSiteGroup(string name, string role)
        {
            SPGroup group = GetGroup(name);
            if (group == null)
            {
                return;
            }

            switch (role)
            {
                case "Owner":
                    Logger.Info("Associating group " + group.Name + " for role " + role);
                    web.AssociatedOwnerGroup = group;
                    role = "Full Control";
                    break;

                case "Member":
                    Logger.Info("Associating group " + group.Name + " for role " + role);
                    web.AssociatedMemberGroup = group;
                    role = "Contribute";
                    break;

                case "Visitor":
                    Logger.Info("Associating group " + group.Name + " for role " + role);
                    web.AssociatedVisitorGroup = group;
                    role = "Read";
                    break;

            }

            SPRoleDefinition roleDef;
            try
            {
                roleDef = web.RoleDefinitions[role];
            }
            catch (SPException)
            {
                Logger.Info("Unrecognized role: " + role);
                return;
            }

            SPRoleAssignment assignment = new SPRoleAssignment(group);
            assignment.RoleDefinitionBindings.Add(roleDef);
            web.RoleAssignments.Add(assignment);
            web.Update();
        }

        private SPGroup GetGroup(string name)
        {
            name = ParserUtil.ReplaceLiveFields(name, web);

            if (name.Contains(",") || name.Contains("'") || name.Contains(".") || name.Contains(":"))
            {
                name = name.Replace(",", "").Replace("'", "").Replace(".", "").Replace(":", "");
            }

            return AclUtil.ResolveSiteGroup(name, web);
        }

        public void AddWebUser(string loginName, string displayName, string email, string description)
        {
            if (string.IsNullOrEmpty(displayName))
                displayName = loginName;

            Logger.Info("Adding user record: " + loginName);
            SPUser user = AclUtil.ResolveUser(loginName, web);

            if (user == null)
            {
                //TODO: Check that this.Description can be null
                if (!string.IsNullOrEmpty(email)/* && !string.IsNullOrEmpty(this.Description)*/)
                {
                    try
                    {
                        web.AllUsers.Add(loginName, email, displayName, description);
                    }
                    catch (SPException e)
                    {
                        Logger.Error(e);
                    }
                }
            }
        }

        public void RemoveWebUser(string loginName)
        {
            Logger.Info("Removing user from site: " + loginName);
            try
            {
                web.AllUsers.Remove(loginName);
            }
            catch (SPException)
            {
                Logger.Info("Could not remove ");
            }
        }
    }

    public class PSGroup : PSObject
    {
        private SPGroup group;

        public PSGroup(string name, string description, SPWeb web)
            : base(web)
        {
            group = AclUtil.CreateWebGroup(name, description, web);
            if (group == null)
            {
                throw new InvalidOperationException("Can't create group: " + name);
            }
        }

        public bool AllowMembersEditMembership
        {
            get { return group.AllowMembersEditMembership; }
            set { group.AllowMembersEditMembership = value; }
        }

        public bool AllowRequestToJoinLeave
        {
            get { return group.AllowRequestToJoinLeave; }
            set { group.AllowRequestToJoinLeave = value; }
        }

        public bool AutoAcceptRequestToJoinLeave
        {
            get { return group.AutoAcceptRequestToJoinLeave; }
            set { group.AutoAcceptRequestToJoinLeave = value; }
        }

        public bool OnlyAllowMembersViewMembership
        {
            get { return group.OnlyAllowMembersViewMembership; }
            set { group.OnlyAllowMembersViewMembership = value; }
        }

        public string RequestToJoinLeaveEmailSetting
        {
            get { return group.RequestToJoinLeaveEmailSetting; }
            set
            {
                if (!string.IsNullOrEmpty(value))
                {
                    group.RequestToJoinLeaveEmailSetting =
                        ParserUtil.ReplaceLiveFields(value, Web);
                }
            }
        }

        public void SetOwner(string owner)
        {
            if (!string.IsNullOrEmpty(owner))
            {
                owner = ParserUtil.ReplaceLiveFields(owner, Web);
                SPWeb rootWeb = Web.Site.RootWeb;
                SPUser user = null;
                try
                {
                    user = rootWeb.Users[owner];
                }
                catch (SPException)
                {
                }

                if (user != null)
                {
                    group.Owner = user;
                }
                else
                {
                    SPGroup owners = null;
                    try
                    {
                        owners = rootWeb.SiteGroups[owner];
                    }
                    catch (SPException)
                    {
                    }

                    if (owners != null)
                    {
                        group.Owner = owners;
                    }
                }
            }
        }

        public void Update()
        {
            group.Update();
        }

    }

    public class PSWeb : IDisposable
    {
        private SPWeb web;
        private bool webOwner;

        public PSWeb(SPWeb web)
        {
            this.web = web;
            webOwner = false;
        }

        public PSWeb(string siteUrl, Guid webGuid)
        {
            using (SPSite site = new SPSite(siteUrl))
            {
                web = site.OpenWeb(webGuid);
                webOwner = true;
            }
        }

        public PSWeb(string siteUrl, string webUrl)
        {
            using (SPSite site = new SPSite(siteUrl))
            {
                web = site.OpenWeb(webUrl);
                webOwner = true;
            }
        }

        public void RestrictSiteTemplates(IEnumerable<Template> templates)
        {
            Dictionary<string, uint> coll = new Dictionary<string, uint>();
            foreach (Template template in templates)
            {
                uint lcid = web.Language;
                if (!string.IsNullOrEmpty(template.LCID))
                {
                    uint.TryParse(template.LCID, out lcid);
                }
                coll.Add(template.Value, lcid);
            }

            WebUtil.RestrictSiteTemplates(web, coll);
            web.Update();
        }

        public PSWeb AddSubweb(string url, string title, string description,
                               uint lcid, string template, bool uniquePermissions, bool inheritTopNav)
        {
            if (string.IsNullOrEmpty(title))
            {
                Logger.Info("Required attribute Title is missing");
                return null;
            }

            if (string.IsNullOrEmpty(template))
            {
                Logger.Info("Required attribute Template is missing");
                return null;
            }

            if (string.IsNullOrEmpty(url))
            {
                Regex cleaner = new Regex(@"[\W]");
                url = cleaner.Replace(title, "").ToLower(CultureInfo.InvariantCulture);
            }


            using (SPWeb newWeb = web.Webs.Add(url, title, description, lcid, template, uniquePermissions, false))
            {
                if (inheritTopNav)
                {
                    newWeb.Navigation.UseShared = true;
                    newWeb.Update();
                }

                return new PSWeb(newWeb.Site.Url, newWeb.Url);
            }
        }

        public void SetProperties(IEnumerable<KeyValuePair<string, string>> properties)
        {
            foreach (KeyValuePair<string, string> pair in properties)
            {
                if (!string.IsNullOrEmpty(pair.Key) && !string.IsNullOrEmpty(pair.Value))
                {
                    string key = pair.Key;
                    string value = pair.Value;

                    if (web.Properties.ContainsKey(key))
                    {
                        web.Properties[key] = value;
                    }
                    else
                    {
                        web.Properties.Add(key, value);
                    }
                }
            }

            web.Properties.Update();
        }


        public void CheckoutFile(string filePath)
        {
            SPFile spFile;// = web.GetFile(filePath);
#if MOSS
            PublishingPage page;
            GetPageFile(filePath, out spFile, out page);
#else
            GetPageFile(filePath, out spFile);
#endif

#if MOSS
            if (page != null && page.ListItem.File.CheckOutStatus == SPFile.SPCheckOutStatus.None)
            {
                page.CheckOut();
                page.Update();
            
            }
            else
#endif

            {
                try
                {
                    spFile.CheckOut();
                    spFile.Update();
                }
                catch (SPException)
                {
                }
            }
        }

        public void CheckinFile(string filePath)
        {
            SPFile spFile;
#if MOSS
            PublishingPage page;
            GetPageFile(filePath, out spFile, out page);
#else
            GetPageFile(filePath, out spFile);
#endif
            const string txt = "Post provisioning modifications";
#if MOSS
        
            if (page != null)
            {
                string comment = txt;
                page.CheckIn(comment);
                spFile.Publish(comment);

                try
                {
                    spFile.Approve(comment);
                }
                catch (SPException)
                {
                }
            }
            else
#endif
            {
                if (spFile.CheckOutStatus != SPFile.SPCheckOutStatus.None)
                {
                    try
                    {
                        spFile.CheckIn(txt);
                        spFile.Publish(txt);
                        spFile.Approve(txt);
                    }
                    catch (SPException)
                    {
                    }
                }
            }
        }

        private void GetPageFile(string filePath, out SPFile spFile
#if MOSS
            , out PublishingPage page
#endif
)
        {
            spFile = web.GetFile(filePath);

            SPListItem item = null;
            try
            {
                item = spFile.Item;
            }
            catch (SPException)
            {
            }
#if MOSS
            page = null;

            if (item != null)
            {
                if (PublishingPage.IsPublishingPage(item))
                {
                    page = PublishingPage.GetPublishingPage(item);
                }
            }
#endif
        }

        public void Dispose()
        {
            if (webOwner && web != null)
            {
                web.Dispose();
            }
        }

        public static void Op(string webUrl, Action<SPWeb> action)
        {
            using (SPSite site = new SPSite(webUrl))
            {
                using (SPWeb spWeb = site.OpenWeb())
                {
                    action(spWeb);
                }
            }
        }
    }
}